package com.example.hello.filter;

import com.example.hello.common.Result;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.crypto.SecretKey;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;

import io.jsonwebtoken.ExpiredJwtException;

@Slf4j
@Component
@RequiredArgsConstructor
public class JwtAuthenticationFilter extends OncePerRequestFilter {
    
    private final SecretKey jwtSecretKey;
    private final ObjectMapper objectMapper;
    private static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();
    
    private static final List<String> WHITELIST = Arrays.asList(
        "/auth/login",
        "/doc.html",            // Swagger UI
        "/webjars/**",         // Swagger 资源
        "/swagger-resources",   // Swagger 配置
        "/v3/api-docs/**",     // OpenAPI 文档
        "/error"               // 错误页面
    );
    
    @Override
    protected boolean shouldNotFilter(HttpServletRequest request) {
        return isWhitelisted(request.getRequestURI());
    }
    
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) 
            throws ServletException, IOException {
        
        // 获取token
        String token = extractToken(request);
        if (token == null) {
            handleAuthError(response, "未登录");
            return;
        }
        
        try {
            // 验证token并获取claims
            Claims claims = parseToken(token);
            
            // 将用户信息放入请求属性中
            request.setAttribute("username", claims.getSubject());
            request.setAttribute("employeeId", claims.get("employeeId"));
            
            chain.doFilter(request, response);
            
        } catch (ExpiredJwtException e) {
            log.warn("Token已过期: {}", e.getMessage());
            handleAuthError(response, "登录已过期，请重新登录");
        } catch (Exception e) {
            log.warn("Token验证失败: {}", e.getMessage());
            handleAuthError(response, "无效的登录凭证");
        }
    }
    
    private String extractToken(HttpServletRequest request) {
        String token = request.getHeader("Authorization");
        if (token != null && token.startsWith("Bearer ")) {
            return token.substring(7);
        }
        return null;
    }
    
    private Claims parseToken(String token) {
        return Jwts.parserBuilder()
            .setSigningKey(jwtSecretKey)
            .build()
            .parseClaimsJws(token)
            .getBody();
    }
    
    private boolean isWhitelisted(String requestURI) {
        return WHITELIST.stream()
            .anyMatch(pattern -> PATH_MATCHER.match(pattern, requestURI));
    }
    
    private void handleAuthError(HttpServletResponse response, String message) throws IOException {
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        response.setCharacterEncoding("UTF-8");
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        
        Result<?> result = Result.error(message);
        response.getWriter().write(objectMapper.writeValueAsString(result));
    }
} 